home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / pascal / memmap.zip / MEMMAP.TXT < prev   
Text File  |  1989-07-08  |  13KB  |  292 lines

  1.                   MemMap:  Map of DOS Memory Blocks
  2.                         Using Turbo Pascal 5.0
  3.  
  4.                                   by
  5.  
  6.                              Earl F. Glynn
  7.                            Overland Park, KS
  8.                          CompuServe 73257,3527
  9.  
  10.                 (C) Copyright 1989, All Rights Reserved.
  11.  
  12.  
  13. Introduction
  14. ------------
  15.  
  16. MemMap is a DOS utility that displays all allocated memory blocks,
  17. including terminate-and-stay-resident (TSR) programs and their
  18. associated environment memory blocks.  With a /V switch, MemMap
  19. displays the variables in each environment block.
  20.  
  21. MemMap has been tested with DOS 2.10, 3.3, 4.0 and OS/2 Extended Edition
  22. 1.1 DOS Command subset.
  23.  
  24. The original motivation for writing MemMap was to determine the amount
  25. of memory lost to needless environment variables being saved every time
  26. a TSR was loaded into memory.  But several other factors shaped the
  27. development of MemMap:
  28.  
  29.      - DOS 4.0 "MEM /DEBUG" functionality is not present in DOS 3.X.
  30.        Some utilities, such as PC Magazine's PCMAP, give part of the
  31.        information desired about TSRs.
  32.  
  33.      - PCMAP returns "unknown" for most program names when run under
  34.        DOS 4.0 (See Figure 1).  Since MEM is a new command under
  35.        DOS 4.0, and cannot be run on earlier DOS versions, a common
  36.        program that operates under both DOS 3.X and 4.X is desirable.
  37.  
  38.      - DOS 4.0 MEM reports block sizes only in hexadecimal bytes, e.g.,
  39.        Sidekick (SKM) is hex 7180 bytes long, instead of decimal
  40.        29056 bytes.
  41.  
  42.      - PCMAP aggregates both environment and program blocks, creating
  43.        two problems:  (1) the memory entries are not always listed
  44.        in ascending order; (2) size information about individual
  45.        environment blocks is not available.
  46.  
  47.      - The size and contents of the environment blocks cannot be
  48.        effectively managed without an easy way to display all variables
  49.        in all environment blocks.
  50.  
  51.      - Several memory map programs have erratic behavior when IBM's
  52.        Workstation Program (INDCIPL.EXE) and Expanded Memory
  53.        Manager (INDXMAA.SYS) are in memory.
  54.  
  55.      - Turbo Pascal can be used to write system utilities as easily
  56.        as assembly language or C.  In particular, MemMap demonstrates
  57.        the ability of Turbo Pascal to manipulate DOS system control
  58.        blocks using pointer variables and record types.
  59.  
  60.  
  61. Background
  62. ----------
  63.  
  64. The layout of DOS user memory is shown in Figure 2.  Following the DOS
  65. system area, each memory block is preceded by a memory control block
  66. (MCB).  This MCB stores information on the owner of the block and
  67. the size of the memory block -- described in Figure 3.  Once the
  68. initial MCB is found, the next MCB follows the memory block.  All
  69. of user memory can be mapped by stepping through, MCB by MCB.  The last
  70. MCB is tagged differently than all other MCBs, so a termination condition
  71. is easily recognized.  But how is the address of the first MCB found?
  72.  
  73. The first Memory Control Block can be found by searching through
  74. memory at paragraph boundaries, or by using the undocumented function
  75. call $52 of DOS interrupt $21.  MemMap uses the latter approach
  76. to obtain the address of the so-called DOS "List of Lists".  At an offset
  77. of -2 in this "List of Lists" is the segment address of the first MCB.
  78.  
  79. The "Type" of an MCB is determined by observing when certain relationships
  80. exist.  If the MCB owner is hex 0000, the block following the MCB is
  81. not allocated and its type is shown as "Free Space".  When the first
  82. word of the paragraph following the MCB is hex 20CD (or possibly
  83. 27CD), the block type is "Program", if the "owner" field points
  84. to this next paragraph; otherwise, the "owner" is assumed to be the DOS
  85. kernel and the block type is shown as "System".  See Figure 4.  The block
  86. type is "Environment" when the block's owner has an environment pointer
  87. back to the paragraph following the MCB.  When none of the above
  88. relationships hold, the block is assumed to have a "Data" type.  (One
  89. TSR that I've found with a "Data" memory block is PC Magazine's
  90. PRN2FILE).
  91.  
  92. The "Name" of an MCB is determined from the environment block when
  93. possible.  In DOS 3.X, the fully-qualified program name follows the
  94. environment value(s) and a special tag word (hex 0001), as shown in
  95. Figure 4.  When an environment block does not exist for a program,
  96. or when the program name does not follow the environment block,
  97. a "short" program name (1-8 characters) can be found in the last
  98. half of the MCB -- but only in DOS 4.0.  In earlier DOS versions
  99. the name is "<unknown>" in such a case.
  100.  
  101.  
  102. Implementation Details for Turbo Pascal 5.0
  103. -------------------------------------------
  104.  
  105. Pointers are usually used to address dynamic variables created with
  106. the standard Pascal NEW procedure (or Turbo Pascal's GetMem procedure),
  107. but pointers can also be used to manipulate existing data structures,
  108. such as DOS memory blocks.  An example of accessing DOS's "List of Lists",
  109. Memory Control Blocks (MCBs) and the Program Segment Prefix (PSP) blocks
  110. using pointer variables is shown in the MemMap Turbo Pascal 5.0 program.
  111. (See Figure 5).
  112.  
  113. To obtain the address of the DOS "List of Lists", the undocumented
  114. function call $52 of DOS interrupt $21 is needed.  The DOS Turbo Pascal
  115. UNIT provides the "Intr" procedure and "Registers" type:
  116.  
  117.      ...
  118.  
  119.      VAR r:  Registers;                {Figure 5, line  57}
  120.      ...
  121.  
  122.      r.AH := $52;                                {line 205}
  123.      Intr ($21,r);                               {line 206}
  124.  
  125. After this DOS interrupt, a pointer to the "List of Lists" is in ES:BX.
  126. At an offset of -2 in the "List of Lists" is the segment address of the
  127. first MCB:
  128.  
  129.      segment := MemW[r.ES:r.BX-2];               {line 207}
  130.  
  131. where the "MemW" Turbo Pascal "system array" returns the word at the
  132. given segment:offset address.  The "MCB" pointer variable is then
  133. defined using the Turbo Pascal "Ptr" procedure:
  134.  
  135.      MCB := Ptr(segment,0);                      {line 210}
  136.  
  137. At this point all the variables defined by the MemoryControlBlock TYPE
  138. can be accessed.  Typecasting can be used to help calculate the size of
  139. the memory block following the MCB:
  140.  
  141.      bytes := LongInt(MCB^.BlockSize) SHL 4;     {line 102}
  142.  
  143. If the MCB^.BlockOwner is zero, the block is free space.  If it is
  144. nonzero, the MCB^.BlockOwner points to a memory block, which is a
  145. valid Program Segment Prefix (PSP) if it starts with the word $20CD
  146. (or possibly $27CD).  The PSP pointer is defined by
  147.  
  148.      psp := Ptr(MCB^.BlockOwner,0);              {line 109}
  149.  
  150. A segment pointer to the environment block is at an offset of hex 2C from
  151. the beginning of the PSP, which is defined by psp^.Environment.
  152. Since the environment block must be immediately preceded by an MCB, the
  153. environment MCB is defined by:
  154.  
  155.      MCBenv := Ptr(psp^.Environment-1,0);        {line 116}
  156.  
  157. If the MCB^.BlockOwner is the same as the MCBenv^.BlockOwner,
  158. environment variables follow in ASCIIZ delimited strings (character
  159. strings ending with a $00).  A null (zero-length) variable marks the
  160. end of the environment.  The program name follows the special
  161. $0001 tag.
  162.  
  163. Once an MCB and its associated information is displayed, the segment
  164. address of the next MCB is found by the statement:
  165.  
  166.      segment := segment + MCB^.Blocksize + 1;    {line 212}
  167.  
  168. The extra "1" above is needed since the MCB is itself a single
  169. paragraph long.
  170.  
  171. Contiguous MCBs and memory blocks can be sequentially listed until
  172. the last MCB is found, which is tagged with MCB^.Blocktag = $5A.
  173.  
  174. A final note:  DO NOT use DISPOSE (or FreeMem) to deallocate
  175. a pointer variable that was not allocated using NEW (or GetMem).
  176. Since the DOS control blocks described above are allocated outside
  177. of MemMap, they should not be deallocated by MemMap.
  178.  
  179.  
  180. Results
  181. -------
  182.  
  183. To demonstrate MemMap, several DOS commands and other TSRs were executed
  184. to create a variety of memory control blocks (after booting without
  185. an AUTOEXEC.BAT or CONFIG.SYS present):
  186.  
  187.      APPEND ..
  188.      GRAPHICS
  189.